﻿using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
//using PlanningGIS.Access;
using PlanningGIS.ArcGIS;
using PlanningGIS.DataConvert.model;
using PlanningGIS.Framework;
using PlanningGIS.MapSheet;
using PlanningGIS.MetaData;
using PlanningGIS.Util.Data;
using PlanningGIS.Util.Log;
using PlanningGIS.Util.Management;
using PlanningGIS.Util.Win32;
using PlanningGIS.Win.Controls;

namespace PlanningGIS.DataConvert
{
    /// <summary>
    /// 导出数据
    /// </summary>
    public class ExportCAD : FrameCAD
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public ExportCAD()
        {
            IsClip = true;
            IsOverlap = false;
        }

        /// <summary>
        /// 要导出的要素类【输入、必需】
        /// </summary>
        public List<IFeatureClass> FeatureClasses { get; set; }

        /// <summary>
        /// 要导出的路径【输入、必需】
        /// </summary>
        public string FullName { get; set; }

        /// <summary>
        /// 导出的范围
        /// </summary>
        public IGeometry ClipExtent { get; set; }

        /// <summary>
        /// 是否存在面的压盖，勾选后比较慢
        /// </summary>
        public bool IsOverlap { get; set; }

        /// <summary>
        /// 要导出的图幅
        /// </summary>
        public List<Mapsheet> Sheets { get; set; }

        /// <summary>
        /// 是否裁切
        /// </summary>
        public bool IsClip { get; set; }

        /// <summary>
        /// 获取或设置导出时是否有元数据信息
        /// </summary>
        public bool HasMeta { get; set; }

        /// <summary>
        /// 获取或设置导出时是否有图廓
        /// </summary>
        public bool HasTK { get; set; }

        /// <summary>
        /// 获取或设置是否使用自定义的元数据
        /// </summary>
        public bool CustomMeta { get; set; }

        /// <summary>
        /// 获取或设置元数据的指
        /// </summary>
        public Dictionary<string, string> MetaValues { get; set; }

        /// <summary>
        /// 是否停止导出
        /// </summary>
        private bool _IsStop = false;

        /// <summary>
        /// 获取或设置分进度条
        /// </summary>
        public Progressor ProgressSub { get; set; }

        /// <summary>
        /// 获取或设置总进度条
        /// </summary>
        public Progressor ProgressAll { get; set; }

        /// <summary>
        /// 分类代码表
        /// </summary>
        protected DataTable _FcodeTable = null;

        /// <summary>
        /// 线面重叠要素进行处理的配置表
        /// </summary>
        protected DataTable _OverlapTable = null;

        /// <summary>
        /// 测量标记配置表
        /// </summary>
        protected DataTable _SurveyMarkTable = null;

        /// <summary>
        /// 面内自动生成注记和点符号的配置表
        /// </summary>
        protected DataTable _AutoGenerationTable = null;

        /// <summary>
        /// 要素遇到要素打断处理的配置表
        /// </summary>
        protected DataTable _FeatureBreakTable = null;

        /// <summary>
        /// 图层中相关字段的索引
        /// </summary>
        protected Dictionary<string, dynamic> _Indexes = null;

        /// <summary>
        /// 是否根据图幅导出
        /// </summary>
        /// <param name="isSheet">是否按图幅导出</param>
        public bool Export(bool isSheet)
        {
            if (FeatureClasses == null || FeatureClasses.Count == 0 || string.IsNullOrWhiteSpace(FullName)) return false;
            LogHelper.WriteLog("参数验证完成，正在启动CAD，请稍等...");
            try
            {
                if (!StartCAD()) return false;
                LogHelper.WriteLog("正在初始化系统配置信息...");
                string cfg = AppConfig.ConfigPath + "\\CadConfig.mdb";
                if (File.Exists(cfg))
                {
                    //IDbContext dbcontext = new AccessContext(cfg);
                    //_FcodeTable = dbcontext.GetDataTable("select * from features ");
                    //_OverlapTable = dbcontext.GetDataTable("select * from Overlap ");
                    //_SurveyMarkTable = dbcontext.GetDataTable("select * from SurveyMark ");
                    //_AutoGenerationTable = dbcontext.GetDataTable("select * from AutoGeneration ");
                }
                UnitValue = SheetHelper.Config.UnitValue;
                UnitName = MetaHelper.FrameConfig.UnitName;
                SecurityLevel = MetaHelper.FrameConfig.SecurityLevel;
                if (isSheet)
                {
                    SheetScale st = SheetHelper.Config.ScaleTypes.FirstOrDefault(t => t.Value == Scale);
                    XOffset = st.XOffset;
                    YOffset = st.YOffset;
                }
                LogHelper.WriteLog("开始导出数据，该过程可能花费比较长的时间，请耐心等待..."); 
                if (isSheet) ExportSheet();
                else ExportGeometry();
                return true;
            }
            catch (System.Exception ex)
            {
                LogHelper.WriteErrLog("Dwg导出失败：" + ex.Message);
                return false;
            }
        }

        /// <summary>
        /// 停止导出
        /// </summary>
        public void Stop()
        {
            _IsStop = true;            
        }

        /// <summary>
        ///　按照范围导出
        /// </summary>
        protected void ExportGeometry()
        {
            if (System.IO.File.Exists(FullName))
            {
                try
                {
                    System.IO.File.Delete(FullName);
                }
                catch
                {
                    LogHelper.WriteLog("对文件‘" + FullName + "’覆盖失败！");
                    return;
                }
            }
            CadDocument = CadApplication.Documents.Add("acadiso.dwt");
            if (HasTK)
                DrawSheet(ClipExtent.Envelope); 
            ProgressAll.SetMaxValue(FeatureClasses.Count);
            foreach (dynamic cls in FeatureClasses)
            {
                if (_IsStop) break;
                ExportFeatureClass((IFeatureClass)cls);
                Application.DoEvents();
                ProgressAll.Step();
            }
            ProgressAll.Stop();
            if (!_IsStop)
            {
                CadDocument.SaveAs(FullName, AcSaveAsType.acNative, null);
                LogHelper.WriteLog("导出到文件‘" + FullName + "’成功！");
            }
            CadDocument.Close(false, "");
            Marshal.ReleaseComObject(CadDocument);
            CadDocument = null;
        }
        
        #region 图幅相关

        /// <summary>
        /// 按图幅导出
        /// </summary>
        protected void ExportSheet()
        {
            if (Sheets == null || Sheets.Count == 0) return;
            DataTable _MetaTable = null;
            if (HasMeta && !CustomMeta)
            {
                try
                {
                    var v = from p in Sheets
                            select p.Code;
                    _MetaTable = MetaHelper.GetMetaInfos(v.ToList());
                }
                catch
                {
                    
                }                
            }
            try
            {                
                foreach (Mapsheet itm in Sheets)
                {
                    if (_IsStop) break;
                    LogHelper.WriteLog("开始导出图幅:" + itm.Code);
                    CadDocument = CadApplication.Documents.Add("acadiso.dwt");
                    _LayerNames = new List<string>();
                    CadDocument.Activate();
                    ClipExtent = itm.Geometry;
                    if (HasMeta)
                        MetaHelper.GetMetaInfo(itm.Code, _MetaTable, MetaValues, out _LeftValues, out _RightValues);
                    ProgressAll.SetMaxValue(FeatureClasses.Count);
                    if (HasTK)
                        InsertMapSheet(itm);
                    foreach (dynamic cls in FeatureClasses)
                    {
                        if (_IsStop) break;
                        ProgressAll.Step();
                        ExportFeatureClass(cls);
                        Application.DoEvents();
                    }
                    ProgressAll.Stop();
                    if (!_IsStop)
                    {
                        string fileName = string.Format("{0}\\{1}.dwg", FullName, itm.Code);
                        if (FullName.EndsWith("\\")) fileName = string.Format("{0}{1}.dwg", FullName, itm.Code);
                        CadDocument.SaveAs(fileName, AcSaveAsType.acNative, null);
                        LogHelper.WriteLog("导出到文件‘" + fileName + "’成功！");
                    }
                    CadDocument.Close(false, "");
                    Marshal.ReleaseComObject(CadDocument);
                    CadDocument = null;
                }
                
            }
            catch (System.Exception ex)
            {
                LogHelper.WriteErrLog("导出图幅出错，错误信息：" + ex.Message);
            }
        }

        /// <summary>
        /// 插入图廓与图廓整式
        /// </summary>
        /// <param name="sheet"></param>
        protected void InsertMapSheet(Mapsheet sheet)
        {
            SheetCodes = sheet.UserData;
            SheetCode = sheet.Code;
            SheetName = sheet.Name;            
            bool hastk = false;
            string tk = string.Format("{0}\\blocks\\图廓\\TK{1}.dwg", AppConfig.StartupPath, Scale.ToString());
            if (File.Exists(tk))
            {
                try
                {
                    //CreateCadLayer("TK");
                    hastk = true;
                    IAcadBlockReference br = CadDocument.ModelSpace.InsertBlock(new double[] { sheet.Geometry.Envelope.XMin, sheet.Geometry.Envelope.YMin, 0 }, tk, 1, 1, 1, 0, "");
                    br.Layer = _LayerName;
                    br.Explode();
                }
                catch (Exception ex)
                {
                    LogHelper.WriteErrLog("绘制框架有误:" + ex.Message);
                }
            }
            DrawSheet(sheet.Geometry.Envelope, hastk);
            //插入测量标记
            if (_SurveyMarkTable == null || _SurveyMarkTable.Rows.Count == 0) return;
            DataRow[] rows = _SurveyMarkTable.Select("MapNo='" + sheet.Code + "' ");
            if (rows == null || rows.Length == 0) return;
            string fileName = rows[0]["FileName"].ToString();
            string fullFileName = AppConfig.StartupPath + "\\blocks\\测量标志\\" + fileName;
            IPoint pt = new Point();
            pt.X = sheet.Geometry.Envelope.XMin + sheet.Geometry.Envelope.Width / 2;
            pt.Y = sheet.Geometry.Envelope.YMin + sheet.Geometry.Envelope.Height / 2;
            Point2CadBlock(pt, fullFileName, 0, "0", 1, 1, 1);
        }

        #endregion

        /// <summary>
        /// 导出图层中的对象到dwg中
        /// </summary>
        /// <param name="featcls">要导出的图层</param>
        protected void ExportFeatureClass(IFeatureClass featcls)
        {
            string clsName = ((IDataset)featcls).Name;
            int _FcodeIndex = featcls.FindField(AppConfig.SystemConfig.常用字段.分类代码);
            if (_FcodeIndex < 0)
            {
                LogHelper.WriteLog("图层'" + clsName + "'中不存在分类代码字段【" + AppConfig.SystemConfig.常用字段.分类代码 + "】");
                return ;
            }
            LogHelper.WriteLog("开始导出图层'" + clsName + "'");
            ISpatialFilter filter = null;
            if (ClipExtent != null)
            {
                filter = new SpatialFilter();
                filter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
                filter.Geometry = ClipExtent;
            }
            int cnt = featcls.FeatureCount(filter);
            if (cnt == 0)
            {
                LogHelper.WriteLog("图层'" + clsName + "'中没有需要导出的数据");
                return;
            }
            
            ProgressSub.SetMaxValue(cnt);
            IFeature feat = null;
            int sucCnt = 0;
            int noCnt = 0;
            try
            {
                IFeatureCursor cur = featcls.Search(filter, false);
                while ((feat = cur.NextFeature()) != null)
                {
                    if (_IsStop) break;
                    ProgressSub.Step();
                    int rst = -1;
                    string fcode = feat.get_Value(_FcodeIndex).ToString();
                    dynamic info = GetFeatureConfig(fcode);
                    if (info == null)
                    {
                        LogHelper.WriteLog("导出配置代码表CadConfig.mdb中不存在该分类代码【" + fcode + "】，不导出");
                        rst = 2;
                    }
                    else
                    {
                        if (!info.Export)
                        {
                            LogHelper.WriteLog("分类代码【" + fcode + "】不需要导出");
                            rst = 2;
                        }
                        else
                        {
                            string lyrname = CreateCadLayer(info.LayerName);
                            info.LayerName = lyrname;
                            try
                            {
                                if (featcls.FeatureType == esriFeatureType.esriFTAnnotation)
                                    rst = ExportAnno(feat, fcode, info);
                                else if (featcls.ShapeType == esriGeometryType.esriGeometryPoint)
                                    rst = ExportPoint(feat, fcode, info);
                                else if (featcls.ShapeType == esriGeometryType.esriGeometryPolyline)
                                    rst = ExportPolyline(feat, fcode, info);
                                else if (featcls.ShapeType == esriGeometryType.esriGeometryPolygon)
                                    rst = ExportPolygon(feat, fcode, info);
                            }
                            catch (System.Exception ex)
                            {
                                rst = 1;
                                LogHelper.WriteErrLog("图层'" + clsName + "'中ID为'" + feat.OID + "'的要素导出出错：" + ex.Message);
                            }
                        }                        
                    }
                    if (rst == 0) sucCnt++;
                    else if (rst == 2) noCnt++;
                }
                ProgressSub.Stop();
                Marshal.ReleaseComObject(cur);
                string msg = string.Format("图层【{0}】导出完毕,共{1}条，成功{2}条,失败{3}条,不需要导出{4}条", clsName, cnt, sucCnt, (cnt - sucCnt - noCnt), noCnt);
                LogHelper.WriteLog(msg);
            }
            catch (System.Exception ex)
            {
                LogHelper.WriteErrLog("图层'" + clsName + "' 导出时候出错，错误信息:" + ex.Message);
            }
        }

        /// <summary>
        /// 导出注记要素
        /// </summary>
        /// <param name="feature">要导出的对象</param>
        /// <param name="fcode">分类代码</param>
        /// <param name="info">配置信息</param>
        /// <returns>0:成功,1:失败,2:不导出</returns>
        protected int ExportAnno(IFeature feature, string fcode, dynamic info)
        {
            double txtHeight = info.TextHeight;
            IAnnotationFeature annoFeature = feature as IAnnotationFeature;
            IAnnotationClassExtension annoclsExtension = (feature.Class as IFeatureClass).Extension as IAnnotationClassExtension;
            IAcadText cadTxt = null;
            if (ClipExtent != null)
            {
                IRelationalOperator op = ClipExtent as IRelationalOperator;
                IGeometry annoGeometry = feature.ShapeCopy;
                //if (!op.Contains(annoGeometry))
                //{
                //    if (!op.Overlaps(annoGeometry)) return 2;
                    IEnvelope txtEnvelope = annoGeometry.Envelope;
                    double[] coordinates = { txtEnvelope.XMin, txtEnvelope.YMin };
                    IEnvelope filterEnvelope = ClipExtent.Envelope;
                    if (txtEnvelope.XMin < filterEnvelope.XMin)
                        coordinates[0] = filterEnvelope.XMin;
                    else if (txtEnvelope.XMax > filterEnvelope.XMax)
                        coordinates[0] = filterEnvelope.XMax - (txtEnvelope.XMax - txtEnvelope.XMin);
                    if (txtEnvelope.YMin < filterEnvelope.YMin)
                        coordinates[1] = filterEnvelope.YMin;
                    else if (txtEnvelope.YMax > filterEnvelope.YMax)
                        coordinates[1] = filterEnvelope.YMax - (txtEnvelope.YMax - txtEnvelope.YMin);
                    cadTxt = TextElement2CadText(annoFeature.Annotation as ITextElement, coordinates[0], coordinates[1],
                        info.LayerName, txtHeight, info.Style);
                //}
                //else
                //    cadTxt = TextElement2CadText(annoFeature.Annotation as ITextElement, layerName, txtHeight, info.Style);
            }
            else
                cadTxt = TextElement2CadText(annoFeature.Annotation as ITextElement, info.LayerName, txtHeight, info.Style);
            if (cadTxt != null)
            {
                SaveCadProperty(feature, cadTxt);
                Marshal.ReleaseComObject(cadTxt);
                cadTxt = null;
                return 0;
            }
            else
            {
                LogHelper.WriteErrLog("注记ID为" + feature.OID + "的要素导出失败");
                return 1;
            }
        }

        /// <summary>
        /// 导出点要素
        /// </summary>
        /// <param name="feature">要导出的对象</param>
        /// <param name="fcode">分类代码</param>
        /// <param name="info">配置信息</param>
        /// <returns>0:成功,1:失败,2:不导出</returns>
        protected int ExportPoint(IFeature feature, string fcode, dynamic info)
        {
            double dblAngle = GetAngle(feature);
            string strBlockFile = AppConfig.StartupPath + @"\blocks\点符号\" + fcode + ".dwg";
            if (!File.Exists(strBlockFile))
                strBlockFile = AppConfig.StartupPath + @"\blocks\点符号\gc200.dwg";

            IPoint point = feature.ShapeCopy as IPoint;            
            IAcadEntity pBlock = null;
            if (File.Exists(strBlockFile))
            {                
                if (Sheets != null)
                    pBlock = Point2CadBlock(point, strBlockFile, -dblAngle, info.LayerName, Scale / 500 / 2.0, Scale / 500 / 2.0, 1);
                else
                    pBlock = Point2CadBlock(point, strBlockFile, -dblAngle, info.LayerName, 0.5, 0.5, 1);
            }
            else
            {
                pBlock = Point2CadPoint(point, info.LayerName);
            }            
            if (pBlock != null)
            {
                SaveCadProperty(feature, pBlock);
                Marshal.ReleaseComObject(pBlock);
                pBlock = null;
                return 0;
            }
            else
            {
                LogHelper.WriteErrLog("点要素ID为" + feature.OID + "的要素导出失败");
                return 1;
            }
        }

        /// <summary>
        /// 导出线要素
        /// </summary>
        /// <param name="feature"></param>
        /// <param name="fcode">分类代码</param>
        /// <param name="info">配置信息</param>
        /// <returns>0:成功,1:失败,2:不导出</returns>
        protected int ExportPolyline(IFeature feature, string fcode, dynamic info)
        {    
            IGeometry geo = feature.Shape;
            if (ClipExtent != null && IsClip)
            {
                geo = GeometryHelper.CutFeatByPolygon(geo, ClipExtent, geo.Dimension);
                if (geo == null || geo.IsEmpty) return 2;//线的端点与裁剪区域相交，但是裁剪后为空。
            }
            List<IAcadLWPolyline> cadPolylines = Polyline2CadPolyline(geo as IPolyline, info.LayerName, info.Style);
            if (cadPolylines.Count > 0)
            {
                foreach (IAcadLWPolyline cadPolyline in cadPolylines)
                {
                    SaveCadProperty(feature, cadPolyline);
                    if (cadPolyline != null) Marshal.ReleaseComObject(cadPolyline);
                }
                return 0;
            }
            else
            {
                LogHelper.WriteErrLog("线要素ID为" + feature.OID + "的要素导出失败");
                return 1;
            }
        }

        /// <summary>
        /// 导出面要素
        /// </summary>
        /// <param name="feature"></param>
        /// <param name="fcode">分类代码</param>
        /// <param name="info">配置信息</param>
        /// <returns>0:成功,1:失败,2:不导出</returns>
        protected int ExportPolygon(IFeature feature, string fcode, dynamic info)
        {
            IGeometry geo = feature.Shape;
            bool contain = true;
            IRelationalOperator rel = null;
            if (ClipExtent != null && IsClip)
            {
                if (ClipExtent.SpatialReference != geo.SpatialReference)
                    geo.Project(ClipExtent.SpatialReference);
                rel = ClipExtent as IRelationalOperator;
                contain = rel.Contains(geo);
            }
            IPolygon PY = null;
            if (ClipExtent != null && IsClip && !contain) // 裁切，且图廓和面相交
            {
                ClipPolygon(feature, fcode, info.LayerName, out PY);
            }
            else //不裁切 或者 图廓完全包含面， 面导出为闭合线
            {
                NoClipPolygon(feature, fcode, info.LayerName, out PY);
            }
            ExportField(feature, PY, info.LayerName);
            return 0;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="feature"></param>
        /// <param name="fcode"></param>
        /// <param name="layername"></param>
        /// <returns></returns>
        protected int ClipPolygon(IFeature feature, string fcode, string layername, out IPolygon PY)
        {
            IGeometry geo = feature.Shape;
            IPolyline bdy = (geo as ITopologicalOperator).Boundary as IPolyline;
            PY = GeometryHelper.CutFeatByPolygon(geo, ClipExtent, esriGeometryDimension.esriGeometry2Dimension) as IPolygon;
            IPolyline pl = GeometryHelper.CutFeatByPolygon(bdy, ClipExtent, bdy.Dimension) as IPolyline;
            IPolyline removeOverlapPL = RemoveOverlap(pl, fcode);
            if (removeOverlapPL == null || !removeOverlapPL.IsEmpty)
            {
                List<IAcadLWPolyline> cadPolylines = null;
                if (removeOverlapPL != null)
                    cadPolylines = Polyline2CadPolyline(removeOverlapPL, layername, "");
                else
                    cadPolylines = Polyline2CadPolyline(pl as IPolyline, layername, "");
                if (cadPolylines.Count > 0)
                {
                    foreach (IAcadLWPolyline cadPolyline in cadPolylines)
                    {
                        SaveCadProperty(feature, cadPolyline);
                        if (cadPolyline != null) Marshal.ReleaseComObject(cadPolyline);
                    }
                }
                else
                {
                    LogHelper.WriteErrLog("面要素ID为" + feature.OID + "的要素导出失败");
                    return 1;
                }
            }
            return 0;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="feature"></param>
        /// <param name="fcode"></param>
        /// <param name="layername"></param>
        /// <param name="PY"></param>
        /// <returns></returns>
        protected int NoClipPolygon(IFeature feature, string fcode, string layername, out IPolygon PY)
        {
            IGeometry geo = feature.Shape;
            PY = geo as IPolygon;
            IPolyline removeOverlapPL = RemoveOverlap(geo as IPolygon, fcode);            
            if (removeOverlapPL == null || !removeOverlapPL.IsEmpty)
            {
                List<IAcadLWPolyline> cadPolylines = null;
                if (removeOverlapPL != null)
                    cadPolylines = Polyline2CadPolyline(removeOverlapPL, layername, "");
                else
                    cadPolylines = Polygon2CadPolyline(geo as IPolygon, layername, "");
                if (cadPolylines.Count > 0)
                {
                    foreach (IAcadLWPolyline cadPolyline in cadPolylines)
                    {
                        SaveCadProperty(feature, cadPolyline);
                        if (cadPolyline != null) Marshal.ReleaseComObject(cadPolyline);
                    }
                }
                else
                {
                    if (removeOverlapPL != null && removeOverlapPL.IsEmpty)
                    {
                        LogHelper.WriteErrLog("面要素ID为" + feature.OID + "的要素导出失败");
                        return 1;
                    }
                }
            }
            return 0;
        }

        /// <summary>
        /// 导入指定字段的属性信息，如居民地面导出时判断将属性[房屋层数]和[建筑结构]导出
        /// </summary>
        /// <param name="feature"></param>
        protected void ExportField(IFeature feature, IGeometry py, string layerName)
        {
            int cn = 0;
            foreach (DataRow row in _AutoGenerationTable.Rows)
            {
                object obj = row["FieldName"];
                if (obj == null || obj == DBNull.Value) continue;
                string fdname = obj.ToString();
                int idx = feature.Fields.FindField(fdname);
                if (idx < 0) continue;
                object value = feature.get_Value(idx);
                IPoint lblPoint = (py as IArea).LabelPoint;
                if (cn == 0)
                {
                    lblPoint.X = lblPoint.X + 0.2;
                    Text2CadText(value.ToString(), lblPoint, AcAlignment.acAlignmentMiddleLeft, layerName, 1, "");
                    cn++;
                }
                else
                {
                    lblPoint.X = lblPoint.X - 0.4;
                    Text2CadText(value.ToString(), lblPoint, AcAlignment.acAlignmentMiddleRight, layerName, 1, "");
                }
            }
        }

        /// <summary>
        /// 根据分类代码处理压盖
        /// </summary>
        /// <param name="geo"></param>
        /// <param name="fcode"></param>
        /// <returns></returns>
        protected IPolyline RemoveOverlap(IGeometry geo, string fcode)
        {
            IPolyline resultGeo = null;
            if (_OverlapTable == null || !IsOverlap) return resultGeo;    
            ISpatialFilter spaFilter = new SpatialFilter();
            spaFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
            foreach (DataRow row in _OverlapTable.Rows)
            {
                if (!Regex.IsMatch(fcode, row["PolygonFcode"].ToString())) continue;
                double buffer = 0.05;
                if (_OverlapTable.Columns.Contains("Buffer") && row["Buffer"] != null && row["Buffer"] != DBNull.Value)
                    buffer = Double.Parse(row["Buffer"].ToString());
                spaFilter.Geometry = GeometryHelper.GetBuffer(geo, buffer);
                foreach (IFeatureClass itmcls in this.FeatureClasses)
                {
                    if (itmcls.ShapeType != esriGeometryType.esriGeometryPolyline) continue;
                    IFeatureCursor cursor = itmcls.Search(spaFilter, false);
                    IFeature feature = null;
                    while ((feature = cursor.NextFeature()) != null)
                    {
                        string linecode = GetFcode(feature);
                        if (Regex.IsMatch(linecode, row["LineFcode"].ToString()))
                        {
                            if (resultGeo == null)
                                resultGeo = GeometryHelper.DiffFromIntersect(geo, feature.Shape as IPolyline, buffer, false);
                            else
                                resultGeo = GeometryHelper.DiffFromIntersect(resultGeo, feature.Shape as IPolyline, buffer, false);
                        }
                    }
                }
            }
            return resultGeo;
        }

        /// <summary>
        /// 保存cad属性信息
        /// </summary>
        /// <param name="feature"></param>
        /// <param name="entity"></param>
        protected void SaveCadProperty(IFeature feature, IAcadEntity entity)
        {
            IFields flds = feature.Fields;
            int count = flds.FieldCount;
            short[] xdataType = new short[4] { 1001, 1002, 0, 1002 };
            object[] xdataValue = new object[4] { null, "{", null, "}" };
            List<short> type = new List<short>();
            List<object> values = new List<object>();
            type.Add(1001);
            values.Add("draw_info");
            try
            {               
                for (int i = 0; i < count; i++)
                {
                    IField fld = flds.get_Field(i);
                    if (AppConfig.SystemConfig.常用字段.分类代码.Equals(fld.Name,StringComparison.CurrentCultureIgnoreCase))
                    {
                        double fcode;
                        double.TryParse(feature.get_Value(i).ToString(), out fcode);
                        if (entity is IAcadLWPolyline)
                            (entity as IAcadLWPolyline).Thickness = fcode;
                        else if (entity is IAcadText)
                            (entity as IAcadText).Thickness = fcode;
                        continue;
                    }
                    if (!fld.Editable || fld.Type == esriFieldType.esriFieldTypeGeometry
                        || fld.Type== esriFieldType.esriFieldTypeBlob) continue;
                    if (fld.Name.ToLower() == "shape_area" || 
                        fld.Name.ToLower() == "shape_length" || 
                        fld.Name.ToLower() == "shape_len" || 
                        fld.Name.ToLower() == "shape") continue;
                    type.Add(1000);
                    values.Add(feature.get_Value(i) == DBNull.Value ? "0" : feature.get_Value(i).ToString());
                }
                entity.SetXData(type.ToArray(), values.ToArray());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("属性设有误置：" + ex.Message);
            }
        }

        /// <summary>
        /// 获取点状要素的旋转角度属性值
        /// </summary>
        /// <param name="feature"></param>
        /// <returns></returns>
        protected double GetAngle(IFeature feature)
        {
            int index = feature.Fields.FindField(AppConfig.SystemConfig.常用字段.旋转角度);
            if (index < 0) return 0;
            object obj = feature.get_Value(index);
            if (obj == null || string.IsNullOrWhiteSpace(obj.ToString())) return 0;
            double dblAngle = 0;
            if (double.TryParse(obj.ToString().Trim(), out  dblAngle)) return dblAngle;
            return dblAngle;
        }

        /// <summary>
        /// 获取要素分类代码
        /// </summary>
        /// <param name="feature"></param>
        /// <returns></returns>
        protected string GetFcode(IFeature feature)
        {
            string strFcode = "";
            int index = feature.Fields.FindField(AppConfig.SystemConfig.常用字段.分类代码);
            if (index >= 0)
            {
                strFcode = feature.get_Value(index).ToString().Trim();
            }
            return strFcode;
        }

        /// <summary>
        /// 获取要素配置信息
        /// </summary>
        /// <param name="fcode"></param>
        /// <returns></returns>
        protected dynamic GetFeatureConfig(string fcode)
        {
            DataRow[] rows = _FcodeTable.Select("fcode='" + fcode + "'");
            if (rows == null || rows.Length == 0) return null;
            dynamic info = new ExpandoObject();
            info.ID = rows[0]["ID"] == DBNull.Value ? "" : rows[0]["ID"].ToString();
            info.Fcode = rows[0]["Fcode"] == DBNull.Value ? "" : rows[0]["Fcode"].ToString();
            info.Fname = rows[0]["Fname"] == DBNull.Value ? "" : rows[0]["Fname"].ToString();
            info.Style = rows[0]["Style"] == DBNull.Value ? "Standard" : rows[0]["Style"].ToString();
            info.LayerName = rows[0]["LayerName"] == DBNull.Value ? "" : rows[0]["LayerName"].ToString();
            info.TextHeight = rows[0]["TextHeight"] == DBNull.Value ? 3 : double.Parse(rows[0]["TextHeight"].ToString());
            info.Export = rows[0]["Export"] == DBNull.Value ? false : Convert.ToBoolean(rows[0]["Export"]);
            return info; 
        }

    }


}
